哈囉,各位邦友們!
昨天我們把單一 hero 綁到畫面,並用 @if/@else 來控制顯示。
今天把單一資料改成多筆,學習用 @for 來渲染。
<app-hero-badge> 正常一、建立 heroes 清單
// src/app/app.ts
import { Component, signal } from '@angular/core';
import { HeroBadge } from './hero-badge/hero-badge';
type Hero = { id: number; name: string; rank?: string };
@Component({
  selector: 'app-root',
  imports: [HeroBadge],
  templateUrl: './app.html',
  styleUrl: './app.scss'
})
export class App {
  protected readonly title = signal('hero-journey');
  // 英雄清單
  protected readonly heroes = signal<Hero[]>([
    { id: 11, name: 'Dr Nice', rank: 'B' },
    { id: 12, name: 'Narco', rank: 'A' },
    { id: 13, name: 'Bombasto' },
    { id: 14, name: 'Celeritas', rank: 'S' }
  ]);
  // constructor() {
  //   this.heroes.set([]);
  // }
}
二、範本用 @for + track + @empty
<!-- src/app/app.html -->
<h1>Hello, {{ title() }}</h1>
<section>
  <h2>Heroes</h2>
  <ul>
    @for (h of heroes(); track h.id; let i = $index; let c = $count) {
      <li
        [class.is-a]="h.rank === 'A' || h.rank === 'S'"
        [attr.data-id]="h.id">
        <span class="no">{{ i + 1 }}/{{ c }}</span>
        <span class="name">{{ h.name }}</span>
        @if (h.rank) { <span class="rank">[{{ h.rank }}]</span> }
      </li>
    } @empty {
      <li class="muted">No heroes.</li>
    }
  </ul>
</section>
<!-- 保留 Day03 範例 -->
<app-hero-badge></app-hero-badge>
三、新增樣式
// src/app/app.scss
/* ...existing code... */
ul { 
    list-style: none; 
    padding: 0; 
    margin: 0;
}
li { 
    display: flex; 
    gap: 8px; 
    align-items: baseline; 
    padding: 4px 0; 
}
.no { 
    width: 56px;
    color: #789;
}
.name { 
    font-weight: 600;
}
.rank { 
    color: #445;
    background: #eef;
    padding: 2px 6px;
    border-radius: 4px;
}
/* ...existing code... */
重點:
驗收清單:
 
 
常見錯誤與排查:
今日小結:
現在你已經會用 @for 渲染清單,並學會track以及$index、$count等變數的使用,其他的變數可參考官網的內容做學習。
明天會加入事件處理:點擊列表項目選擇英雄,並用 signal 管理「目前選中」的狀態。
參考資料: